﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SPMonkey.Core
{
    public class GenericComparer<T> : IComparer<T>
    {
        protected Func<T, T, int> comparer { get; set; }

        public GenericComparer(Func<T, T, int> comparer)
        {
            this.comparer = comparer;
        }

        #region IComparer<T> Members

        public int Compare(T x, T y)
        {
            throw new NotImplementedException();
        }

        #endregion
    }

    public class GenericEqualityComparer<T> : IEqualityComparer<T>
    {
        protected Func<T, int> getKey { get; set; }

        public GenericEqualityComparer(Func<T, int> getKey)
        {
            this.getKey = getKey;
        }

        #region IEqualityComparer<T> Members

        public bool Equals(T x, T y)
        {
            return getKey(x).Equals(getKey(y));
        }

        public int GetHashCode(T obj)
        {
            return getKey(obj);
        }

        #endregion
    }

    public static class LinqExtensions
    {
        public static void ForEach<T>(this IEnumerable<T> col, Action<T> action)
        {
            foreach (var item in col)
            {
                action(item);
            }
        }

        public static IEnumerable<T> Union<T>(this IEnumerable<T> source, IEnumerable<T> second, Func<T, int> getKey)
        {
            return source.Union<T>(second, new GenericEqualityComparer<T>(getKey));
        }

        public static bool Contains<T>(this IEnumerable<T> source, T value, Func<T, int> getKey)
        {
            return source.Contains<T>(value, new GenericEqualityComparer<T>(getKey));
        }

        public static IEnumerable<T> Except<T>(this IEnumerable<T> source, IEnumerable<T> second, Func<T, int> getKey)
        {
            return source.Except<T>(second, new GenericEqualityComparer<T>(getKey));
        }

        public static IEnumerable<T> Distinct<T>(this IEnumerable<T> source, Func<T, int> getKey)
        {
            return source.Distinct<T>(new GenericEqualityComparer<T>(getKey));
        }

        public static IEnumerable<IEnumerable<T>> Batch<T>(this IEnumerable<T> source, int batchSize)
        {
            for (IEnumerable<T> s = source; s.Any(); s = s.Skip(batchSize)) yield return s.Take(batchSize);
        }
    }
}
